#pragma once

#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <cstring>
#include <fstream>

#include "../comm/util.hpp"
#include "../comm/log.hpp"

namespace ns_compile
{
  using namespace ns_util;
  using namespace ns_log;
  class Compile
  {
  public:
    // 需要对这个文件名添加后缀
    // 让子进程进行编译
    static bool compile(const std::string &filename, const std::string &language)
    {
      pid_t pid = fork();
      if (pid < 0)
      {
        LOG(ERROR) << "创建子进程失败" << std::endl;
        return false;
      }
      else if (pid == 0)
      {
        umask(0);
        // 编译源文件出错，把错误信息写入错误文件中，需要进行重定向
        int fd = open(PathUtil::compileError(filename).c_str(), O_CREAT | O_WRONLY, 0644);
        if (fd < 0)
        {
          // 打开、创建保存错误信息的文件失败
          LOG(FALSE) << "打开、创建保存错误信息的文件失败" << std::endl;
          exit(2);
        }
        // 重定向
        dup2(fd, 2);

        if (language == "cpp")
        {
          std::string cmd = "g++ -std=c++11 -o " + PathUtil::exe(filename) + " " + PathUtil::src(filename, language);
          int ret = system(cmd.c_str());
          if (ret != 0)
          {
            LOG(ERROR) << "编译失败" << std::endl;
            exit(1);
          }
          exit(0);
        }
        else if (language == "python")
        {
          // Python不需要编译，直接返回true
          exit(0);
        }
        else if (language == "c")
        {
          std::string cmd = "gcc -std=c11 -o " + PathUtil::exe(filename) + " " + PathUtil::src(filename, language);
          int ret = system(cmd.c_str());
          if (ret != 0)
          {
            LOG(ERROR) << "编译失败" << std::endl;
            exit(1);
          }
          exit(0);
        }
        else if (language == "go")
        {
          std::string cmd = "go build -o " + PathUtil::exe(filename) + " " + PathUtil::src(filename, language);
          int ret = system(cmd.c_str());
          if (ret != 0)
          {
            LOG(ERROR) << "编译失败" << std::endl;
            exit(1);
          }
          exit(0);
        }
        else
        {
          LOG(ERROR) << "不支持的语言类型: " << language << std::endl;
          exit(3);
        }

        LOG(ERROR) << "启动编译器错误" << std::endl;
        exit(3);
      }
      else
      {
        waitpid(pid, nullptr, 0);
        if (language == "python" || FileUtil::isFileExist(PathUtil::exe(filename)))
        {
          LOG(INFO) << PathUtil::exe(filename) << "编译成功" << std::endl;
          return true;
        }
      }
      LOG(ERROR) << "编译失败，没有形成可执行程序" << std::endl;
      return false;
    }
  };
}
